今天來補充之前沒有提到的 Eloquent 關聯綁定,我們在 Day7 的時候曾規劃過資料庫關聯,Day10-Day12 也曾聊過 Eloquent ORM 的一些用法,而資料庫的關聯模型也可以在 Laravel 用來綁定 Model 物件間的關聯。
定義關聯關係的時候,預設會自動找你在關聯資料表的外鍵 OOXX_id
,但如果你的外鍵是自行設定的名稱,則需覆蓋原本寫法。
一對一的關係是最單純的,我們舉個例子,一個 user 只有一個帳號,我們就可以在 app\Models\User.php
內這樣寫。
class User extends Model{
//需有另一個 Model Account 關聯至此
public function account()
{
// 三種寫法
// 1. Account 模型對應的資料表要有一個欄位 user_id 紀錄外鍵
return $this->hasOne('App\Models\Account');
// 2. 外鍵應該在這邊有一個對應的id
// return $this->hasOne('App\Models\Account', 'user_id');
// 3. 用 User 模型的 id,對應 Account 的外鍵
// return $this->hasOne('App\Models\Account', 'user_id', 'id');
}
}
因此我們即可透過這個定義的關係查到相對應的模型資料。
$account = User::find(1)->account;
相對的,我們也能夠從 Account 反查回 User 表,打開 app/Models/Account.php
。
class Account extends Model{
public function user()
{
return $this->belongsTo('App\Models\User');
// return $this->belongsTo('App\Models\User', 'user_id', 'id');
}
}
$user = Account::find(1)->user;
一對多,我們以一個主管會有多位部屬的關係來舉例。
class Manager extends Model {
public function employees()
{
// 同樣寫法,只是改用 hasMany
return $this->hasMany('App\Models\Employee');
// return $this->hasMany('App\Models\Employee', 'manager_id', 'id');
}
}
透過關聯取得資料
$employees = Post::find(1)->employees;
foreach ($employees as $employee) {
//
}
反向查詢
class Employee extends Model{
public function manager()
{
return $this->belongsTo('App\Models\Manager');
}
}
$manager_email = Employee::find(1)->manager->email;
多對多的關聯我們以前幾天提到的權限操作為例,一位使用者可以有多種權限,而每一個權限也會有多個使用者,於是我們在兩個資料表中間需要再建一張對應表紀錄彼此多對多的關聯。
可以參考我在 Day24 的文章
class User extends Model{
public function roles()
{
// 說明
// $this->belongsToMany('欲產生關聯的模型', '對應表', '外鍵 1', '外鍵 2');
$this->belongsToMany('App\Models\Role', 'user_roles', 'user_id', 'role_id');
}
}
取得該使用者的權限。
$roles = User::find(1)->roles();
反向查詢
class Role extends Model{
public function users()
{
return $this->belongsToMany('App\User', 'user_roles', 'user_id', 'role_id');
}
}
在多對多關聯中,查詢到的資料會多一個 pivot
的屬性紀錄兩個關聯間對應的那張表。
以上就是 Eloquent 關聯模型簡單的例子。
這邊建議大家,在實作這個功能前,請先將資料表的關聯先建立起來,因為他多一層資料庫關聯的建立,才不會讓你在設定模型關聯時沒刪/誤刪重要資料,我之前曾 maintain 過沒有建資料庫關聯的專案,他並沒有 onDelete = cascade 的設定,Laravel 的程式關聯邏輯也有 bug,導致多對多中間的對應表多了一筆不存在的對應關係。
除此之外,在設定兩個資料間的關聯時,我也建議將外鍵、主鍵寫在對應的函數(hasOne
, hasMany
...等)中,才不會有無法關聯的狀況。